package com.thiswhyme.fsplus.sentinel.feign.instancefilter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @description: 不可用实例上下文
 * @author: thiswhyme
 * @date: 2021/4/29
 */
public class BlockServerContext implements CommandLineRunner {

    public static final Logger log = LoggerFactory.getLogger(BlockServerContext.class);

    /**
     * 不可用服务实例容器
     * key：实例IP:PORT
     */
    private Map<String, Long> serverMap = new ConcurrentHashMap<>();

    /**
     * 实例恢复定时器，用于从serverMap中剔除到达断路窗口时间的实例
     */
    private ScheduledThreadPoolExecutor recoveryScheduler = new ScheduledThreadPoolExecutor(1);

    /**
     * 添加不可用实例
     * @param server
     * @param timestamp
     */
    public void add(String server, Long timestamp) {
        serverMap.put(server, timestamp);
        log.info("添加【{}】到不可用实例，当前不可用的实例：{}", server, serverMap);
    }

    /**
     * 获取当前所有不可用实例
     * @return
     */
    public Set<String> getUnAvailableServers(){
        return serverMap.keySet();
    }

    @Override
    public void run(String... args) {
        recoveryScheduler.scheduleAtFixedRate(() -> {
            try {
                long timestamp = System.currentTimeMillis();
                if (!serverMap.isEmpty()) {
                    serverMap.entrySet().removeIf(entry -> entry.getValue() < timestamp);
                    log.info("当前不可用的实例：{}", serverMap);
                }
            } catch (Throwable e) {
                log.error("不可用实例剔除失败", e);
            }
        }, 0, 1, TimeUnit.SECONDS);
    }
}
